package com.yunke.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yunke.common.exception.YunkeAssert;
import com.yunke.common.exception.YunkeException;
import com.yunke.common.result.YunkeResultCode;
import com.yunke.common.security.YunkeSecurityUtil;
import com.yunke.common.util.YunkeTimeUtil;
import com.yunke.dto.dazi.YunkeDaziCreateDto;
import com.yunke.dto.dazi.YunkeDaziJoinDto;
import com.yunke.dto.dazi.YunkeDaziListDto;
import com.yunke.entity.YunkeDazi;
import com.yunke.entity.YunkeDaziJoin;
import com.yunke.entity.YunkeTabClass;
import com.yunke.entity.YunkeUser;
import com.yunke.mapper.YunkeDaziJoinMapper;
import com.yunke.mapper.YunkeDaziMapper;
import com.yunke.mapper.YunkeTabClassMapper;
import com.yunke.service.YunkeDaziService;
import com.yunke.service.YunkeUserService;
import com.yunke.vo.dazi.YunkeDaziDetailVo;
import com.yunke.vo.dazi.YunkeDaziListVo;
import com.yunke.vo.dazi.YunkeTabClassVo;
import com.yunke.util.YunkeDaziStatusUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 云科搭子管理服务实现类
 * 
 * @author yunke
 * @since 2024-01-01
 */
@Slf4j
@Service
public class YunkeDaziServiceImpl extends ServiceImpl<YunkeDaziMapper, YunkeDazi> implements YunkeDaziService {

    @Autowired
    private YunkeDaziMapper daziMapper;

    @Autowired
    private YunkeDaziJoinMapper daziJoinMapper;

    @Autowired
    private YunkeTabClassMapper tabClassMapper;

    @Autowired
    private YunkeUserService userService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    // Redis缓存键前缀
    private static final String CACHE_CATEGORY_KEY = "yunke:dazi:category";
    private static final String CACHE_DAZI_DETAIL_KEY = "yunke:dazi:detail:";
    private static final String CACHE_VIEW_COUNT_KEY = "yunke:dazi:view:";
    private static final String CACHE_LIKE_KEY = "yunke:dazi:like:";

    @Override
    public List<YunkeTabClassVo> getCategoryList() {
        log.info("获取搭子分类列表");
        
        // 先从缓存获取
        List<YunkeTabClassVo> cachedList = (List<YunkeTabClassVo>) redisTemplate.opsForValue().get(CACHE_CATEGORY_KEY);
        if (cachedList != null && !cachedList.isEmpty()) {
            return cachedList;
        }

        // 从数据库查询
        LambdaQueryWrapper<YunkeTabClass> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YunkeTabClass::getStatus, 1)
                .orderByDesc(YunkeTabClass::getWeight)
                .orderByAsc(YunkeTabClass::getId);
        
        List<YunkeTabClass> tabClasses = tabClassMapper.selectList(wrapper);
        
        // 转换为VO
        List<YunkeTabClassVo> voList = tabClasses.stream().map(tabClass -> {
            YunkeTabClassVo vo = new YunkeTabClassVo();
            BeanUtils.copyProperties(tabClass, vo);
            
            // 统计该分类下的搭子数量
            LambdaQueryWrapper<YunkeDazi> daziWrapper = new LambdaQueryWrapper<>();
            daziWrapper.eq(YunkeDazi::getTabClassId, tabClass.getId())
                      .eq(YunkeDazi::getStatus, 1)
                      .eq(YunkeDazi::getAuditStatus, 1);
            vo.setDaziCount(Math.toIntExact(count(daziWrapper)));
            
            return vo;
        }).collect(Collectors.toList());

        // 缓存30分钟
        redisTemplate.opsForValue().set(CACHE_CATEGORY_KEY, voList, 30, TimeUnit.MINUTES);
        
        log.info("获取搭子分类列表成功，数量: {}", voList.size());
        return voList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createDazi(YunkeDaziCreateDto createDto) {
        // 检查登录状态
        YunkeSecurityUtil.checkLogin();
        Long userId = YunkeSecurityUtil.getCurrentUserId();
        
        log.info("发布搭子: userId={}, title={}", userId, createDto.getTitle());
        
        // 验证分类是否存在
        YunkeTabClass tabClass = tabClassMapper.selectById(createDto.getTabClassId());
        YunkeAssert.notNull(tabClass, YunkeResultCode.PARAM_ERROR, "搭子分类不存在");
        YunkeAssert.isTrue(tabClass.getStatus() == 1, YunkeResultCode.PARAM_ERROR, "搭子分类已禁用");
        
        // 验证年龄范围
        if (createDto.getAgeMin() != null && createDto.getAgeMax() != null) {
            YunkeAssert.isTrue(createDto.getAgeMin() <= createDto.getAgeMax(), 
                              YunkeResultCode.PARAM_ERROR, "年龄范围设置错误");
        }
        
        // 验证活动时间
        long currentTime = System.currentTimeMillis();
        YunkeAssert.isTrue(createDto.getActivityTime() > currentTime, 
                          YunkeResultCode.PARAM_ERROR, "活动时间不能早于当前时间");
        
        // 验证报名截止时间
        if (createDto.getDeadlineTime() != null) {
            YunkeAssert.isTrue(createDto.getDeadlineTime() < createDto.getActivityTime(), 
                              YunkeResultCode.PARAM_ERROR, "报名截止时间不能晚于活动时间");
        }
        
        // 创建搭子对象
        YunkeDazi dazi = new YunkeDazi();
        BeanUtils.copyProperties(createDto, dazi);
        
        dazi.setUserId(userId);
        dazi.setJoinedPeople(1); // 发布者算一个人
        dazi.setStatus(1); // 已发布
        dazi.setAuditStatus(1); // 默认审核通过
        dazi.setIsTop(0);
        dazi.setViewCount(0);
        dazi.setLikeCount(0);
        dazi.setCommentCount(0);
        dazi.setShareCount(0);
        dazi.setCreateTime(YunkeTimeUtil.timestampToLocalDateTime(currentTime));
        dazi.setUpdateTime(YunkeTimeUtil.timestampToLocalDateTime(currentTime));
        dazi.setPublishTime(currentTime);
        
        // 处理图片列表
        if (createDto.getImages() != null && !createDto.getImages().isEmpty()) {
            try {
                dazi.setImages(objectMapper.writeValueAsString(createDto.getImages()));
            } catch (JsonProcessingException e) {
                log.error("图片列表序列化失败: {}", e.getMessage());
                throw new YunkeException(YunkeResultCode.SYSTEM_ERROR, "图片数据处理失败");
            }
        }
        
        // 保存搭子
        boolean saveResult = save(dazi);
        YunkeAssert.isTrue(saveResult, YunkeResultCode.SYSTEM_ERROR, "发布搭子失败");
        
        // 创建发布者的参与记录
        YunkeDaziJoin publisherJoin = new YunkeDaziJoin();
        publisherJoin.setDaziId(dazi.getId());
        publisherJoin.setUserId(userId);
        publisherJoin.setStatus(1); // 已通过
        publisherJoin.setIsPublisher(1); // 是发布者
        publisherJoin.setApplyTime(currentTime);
        publisherJoin.setJoinTime(currentTime);
        publisherJoin.setCreateTime(YunkeTimeUtil.timestampToLocalDateTime(currentTime));
        publisherJoin.setUpdateTime(YunkeTimeUtil.timestampToLocalDateTime(currentTime));
        
        boolean joinResult = daziJoinMapper.insert(publisherJoin) > 0;
        YunkeAssert.isTrue(joinResult, YunkeResultCode.SYSTEM_ERROR, "创建参与记录失败");
        
        // 清除分类缓存
        redisTemplate.delete(CACHE_CATEGORY_KEY);
        
        log.info("发布搭子成功: daziId={}, userId={}", dazi.getId(), userId);
        return dazi.getId();
    }

    @Override
    public Page<YunkeDaziListVo> getDaziList(YunkeDaziListDto listDto) {
        log.info("获取搭子列表: {}", listDto);
        
        // 构建查询条件
        LambdaQueryWrapper<YunkeDazi> wrapper = new LambdaQueryWrapper<>();
        
        // 基础过滤条件
        wrapper.eq(YunkeDazi::getStatus, 1) // 已发布
               .eq(YunkeDazi::getAuditStatus, 1); // 审核通过
        
        // 分类筛选
        if (listDto.getTabClassId() != null) {
            wrapper.eq(YunkeDazi::getTabClassId, listDto.getTabClassId());
        }
        
        // 关键词搜索
        if (StringUtils.hasText(listDto.getKeyword())) {
            wrapper.and(w -> w.like(YunkeDazi::getTitle, listDto.getKeyword())
                           .or()
                           .like(YunkeDazi::getContent, listDto.getKeyword()));
        }
        
        // 地点筛选
        if (StringUtils.hasText(listDto.getLocation())) {
            wrapper.like(YunkeDazi::getLocation, listDto.getLocation());
        }
        
        // 状态筛选
        if (listDto.getStatus() != null) {
            wrapper.eq(YunkeDazi::getStatus, listDto.getStatus());
        }
        
        // 性别要求筛选
        if (listDto.getGenderLimit() != null) {
            wrapper.eq(YunkeDazi::getGenderLimit, listDto.getGenderLimit());
        }
        
        // 年龄范围筛选
        if (listDto.getAgeMin() != null && listDto.getAgeMax() != null) {
            wrapper.and(w -> w.isNull(YunkeDazi::getAgeMin)
                           .or(w2 -> w2.le(YunkeDazi::getAgeMin, listDto.getAgeMax())))
                   .and(w -> w.isNull(YunkeDazi::getAgeMax)
                           .or(w2 -> w2.ge(YunkeDazi::getAgeMax, listDto.getAgeMin())));
        }
        
        // 活动时间筛选
        if (listDto.getActivityTimeStart() != null) {
            wrapper.ge(YunkeDazi::getActivityTime, listDto.getActivityTimeStart());
        }
        if (listDto.getActivityTimeEnd() != null) {
            wrapper.le(YunkeDazi::getActivityTime, listDto.getActivityTimeEnd());
        }
        
        // 排序处理
        if (listDto.getOrderBy() != null) {
            switch (listDto.getOrderBy()) {
                case 1: // 最新发布
                    wrapper.orderByDesc(YunkeDazi::getIsTop)
                           .orderByDesc(YunkeDazi::getPublishTime);
                    break;
                case 2: // 活动时间
                    wrapper.orderByDesc(YunkeDazi::getIsTop)
                           .orderByAsc(YunkeDazi::getActivityTime);
                    break;
                case 3: // 人气最高
                    wrapper.orderByDesc(YunkeDazi::getIsTop)
                           .orderByDesc(YunkeDazi::getViewCount)
                           .orderByDesc(YunkeDazi::getLikeCount);
                    break;
                case 4: // 距离最近（需要地理位置信息）
                    // TODO: 实现距离排序
                    wrapper.orderByDesc(YunkeDazi::getPublishTime);
                    break;
                default:
                    wrapper.orderByDesc(YunkeDazi::getIsTop)
                           .orderByDesc(YunkeDazi::getPublishTime);
            }
        } else {
            wrapper.orderByDesc(YunkeDazi::getIsTop)
                   .orderByDesc(YunkeDazi::getPublishTime);
        }
        
        // 分页查询
        Page<YunkeDazi> page = new Page<>(listDto.getCurrent(), listDto.getSize());
        Page<YunkeDazi> daziPage = page(page, wrapper);
        
        // 转换为VO
        Page<YunkeDaziListVo> voPage = new Page<>();
        BeanUtils.copyProperties(daziPage, voPage, "records");
        
        List<YunkeDaziListVo> voList = daziPage.getRecords().stream().map(dazi -> {
            YunkeDaziListVo vo = convertToListVo(dazi);
            
            // 设置当前用户是否已参与
            if (YunkeSecurityUtil.isLogin()) {
                Long currentUserId = YunkeSecurityUtil.getCurrentUserId();
                boolean isJoined = checkUserJoined(dazi.getId(), currentUserId);
                vo.setIsJoined(isJoined ? 1 : 0);
            } else {
                vo.setIsJoined(0);
            }
            
            return vo;
        }).collect(Collectors.toList());
        
        voPage.setRecords(voList);
        
        log.info("获取搭子列表成功，总数: {}", voPage.getTotal());
        return voPage;
    }

    @Override
    public YunkeDaziDetailVo getDaziDetail(Long daziId) {
        log.info("获取搭子详情: daziId={}", daziId);
        
        YunkeAssert.notNull(daziId, YunkeResultCode.PARAM_ERROR, "搭子ID不能为空");
        
        // 先从缓存获取
        String cacheKey = CACHE_DAZI_DETAIL_KEY + daziId;
        YunkeDaziDetailVo cachedDetail = (YunkeDaziDetailVo) redisTemplate.opsForValue().get(cacheKey);
        if (cachedDetail != null) {
            // 更新用户相关状态
            updateUserRelatedStatus(cachedDetail);
            return cachedDetail;
        }
        
        // 从数据库查询
        YunkeDazi dazi = getById(daziId);
        YunkeAssert.notNull(dazi, YunkeResultCode.DATA_NOT_FOUND, "搭子不存在");
        
        // 转换为详情VO
        YunkeDaziDetailVo detailVo = convertToDetailVo(dazi);
        
        // 缓存10分钟
        redisTemplate.opsForValue().set(cacheKey, detailVo, 10, TimeUnit.MINUTES);
        
        // 异步增加浏览次数
        increaseViewCount(daziId);
        
        log.info("获取搭子详情成功: daziId={}", daziId);
        return detailVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean joinDazi(YunkeDaziJoinDto joinDto) {
        // 检查登录状态
        YunkeSecurityUtil.checkLogin();
        Long userId = YunkeSecurityUtil.getCurrentUserId();
        
        log.info("参与搭子: userId={}, daziId={}", userId, joinDto.getDaziId());
        
        // 验证搭子是否存在
        YunkeDazi dazi = getById(joinDto.getDaziId());
        YunkeAssert.notNull(dazi, YunkeResultCode.DATA_NOT_FOUND, "搭子不存在");
        YunkeAssert.isTrue(dazi.getStatus() == 1, YunkeResultCode.PARAM_ERROR, "搭子已关闭");
        YunkeAssert.isTrue(dazi.getAuditStatus() == 1, YunkeResultCode.PARAM_ERROR, "搭子未通过审核");
        
        // 检查是否可以参与
        YunkeAssert.isTrue(canJoinDazi(joinDto.getDaziId(), userId), YunkeResultCode.PARAM_ERROR, "无法参与该搭子");
        
        // 检查是否已经参与
        LambdaQueryWrapper<YunkeDaziJoin> existWrapper = new LambdaQueryWrapper<>();
        existWrapper.eq(YunkeDaziJoin::getDaziId, joinDto.getDaziId())
                   .eq(YunkeDaziJoin::getUserId, userId);
        
        YunkeDaziJoin existJoin = daziJoinMapper.selectOne(existWrapper);
        if (existJoin != null) {
            if (existJoin.getStatus() == 3) { // 已退出，可以重新申请
                existJoin.setApplyReason(joinDto.getApplyReason());
                existJoin.setContact(joinDto.getContact());
                existJoin.setStatus(dazi.getNeedAudit() == 1 ? 0 : 1); // 根据是否需要审核设置状态
                existJoin.setApplyTime(System.currentTimeMillis());
                existJoin.setUpdateTime(YunkeTimeUtil.timestampToLocalDateTime(System.currentTimeMillis()));
                
                if (dazi.getNeedAudit() == 0) { // 不需要审核直接通过
                    existJoin.setJoinTime(System.currentTimeMillis());
                    existJoin.setAuditorId(dazi.getUserId());
                    existJoin.setAuditTime(System.currentTimeMillis());
                    
                    // 增加已加入人数
                    LambdaUpdateWrapper<YunkeDazi> updateWrapper = new LambdaUpdateWrapper<>();
                    updateWrapper.eq(YunkeDazi::getId, joinDto.getDaziId())
                               .setSql("joined_people = joined_people + 1");
                    update(updateWrapper);
                }
                
                boolean updateResult = daziJoinMapper.updateById(existJoin) > 0;
                YunkeAssert.isTrue(updateResult, YunkeResultCode.SYSTEM_ERROR, "重新申请参与失败");
                
                // 清除详情缓存
                redisTemplate.delete(CACHE_DAZI_DETAIL_KEY + joinDto.getDaziId());
                
                log.info("重新申请参与搭子成功: userId={}, daziId={}", userId, joinDto.getDaziId());
                return true;
            } else {
                throw new YunkeException(YunkeResultCode.PARAM_ERROR, "您已经申请参与该搭子");
            }
        }
        
        // 创建新的参与记录
        YunkeDaziJoin join = new YunkeDaziJoin();
        join.setDaziId(joinDto.getDaziId());
        join.setUserId(userId);
        join.setApplyReason(joinDto.getApplyReason());
        join.setContact(joinDto.getContact());
        join.setStatus(dazi.getNeedAudit() == 1 ? 0 : 1); // 根据是否需要审核设置状态
        join.setIsPublisher(0);
        
        long currentTime = System.currentTimeMillis();
        join.setApplyTime(currentTime);
        join.setCreateTime(YunkeTimeUtil.timestampToLocalDateTime(currentTime));
        join.setUpdateTime(YunkeTimeUtil.timestampToLocalDateTime(System.currentTimeMillis()));
        
        if (dazi.getNeedAudit() == 0) { // 不需要审核直接通过
            join.setJoinTime(currentTime);
            join.setAuditorId(dazi.getUserId());
            join.setAuditTime(currentTime);
            
            // 增加已加入人数
            LambdaUpdateWrapper<YunkeDazi> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(YunkeDazi::getId, joinDto.getDaziId())
                       .setSql("joined_people = joined_people + 1");
            update(updateWrapper);
        }
        
        boolean joinResult = daziJoinMapper.insert(join) > 0;
        YunkeAssert.isTrue(joinResult, YunkeResultCode.SYSTEM_ERROR, "参与搭子失败");
        
        // 清除详情缓存
        redisTemplate.delete(CACHE_DAZI_DETAIL_KEY + joinDto.getDaziId());
        
        log.info("参与搭子成功: userId={}, daziId={}, needAudit={}", userId, joinDto.getDaziId(), dazi.getNeedAudit());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean quitDazi(Long daziId, String quitReason) {
        // 检查登录状态
        YunkeSecurityUtil.checkLogin();
        Long userId = YunkeSecurityUtil.getCurrentUserId();
        
        log.info("退出搭子: userId={}, daziId={}", userId, daziId);
        
        // 查找参与记录
        LambdaQueryWrapper<YunkeDaziJoin> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YunkeDaziJoin::getDaziId, daziId)
               .eq(YunkeDaziJoin::getUserId, userId)
               .eq(YunkeDaziJoin::getStatus, 1); // 只有已通过的才能退出
        
        YunkeDaziJoin joinRecord = daziJoinMapper.selectOne(wrapper);
        YunkeAssert.notNull(joinRecord, YunkeResultCode.PARAM_ERROR, "您尚未参与该搭子或申请未通过");
        YunkeAssert.isTrue(joinRecord.getIsPublisher() == 0, YunkeResultCode.PARAM_ERROR, "发布者不能退出搭子");
        
        // 更新参与记录状态
        joinRecord.setStatus(3); // 已退出
        joinRecord.setQuitReason(quitReason);
        joinRecord.setQuitTime(System.currentTimeMillis());
        joinRecord.setUpdateTime(YunkeTimeUtil.timestampToLocalDateTime(System.currentTimeMillis()));
        
        boolean updateResult = daziJoinMapper.updateById(joinRecord) > 0;
        YunkeAssert.isTrue(updateResult, YunkeResultCode.SYSTEM_ERROR, "退出搭子失败");
        
        // 减少已加入人数
        LambdaUpdateWrapper<YunkeDazi> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(YunkeDazi::getId, daziId)
                   .setSql("joined_people = joined_people - 1");
        update(updateWrapper);
        
        // 清除详情缓存
        redisTemplate.delete(CACHE_DAZI_DETAIL_KEY + daziId);
        
        log.info("退出搭子成功: userId={}, daziId={}", userId, daziId);
        return true;
    }

    @Override
    public Page<YunkeDaziListVo> getMyPublishedDazi(Integer current, Integer size, Integer status) {
        // 检查登录状态
        YunkeSecurityUtil.checkLogin();
        Long userId = YunkeSecurityUtil.getCurrentUserId();
        
        log.info("获取我发布的搭子: userId={}, status={}", userId, status);
        
        LambdaQueryWrapper<YunkeDazi> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YunkeDazi::getUserId, userId);
        
        if (status != null) {
            wrapper.eq(YunkeDazi::getStatus, status);
        }
        
        wrapper.orderByDesc(YunkeDazi::getCreateTime);
        
        Page<YunkeDazi> page = new Page<>(current, size);
        Page<YunkeDazi> daziPage = page(page, wrapper);
        
        // 转换为VO
        Page<YunkeDaziListVo> voPage = new Page<>();
        BeanUtils.copyProperties(daziPage, voPage, "records");
        
        List<YunkeDaziListVo> voList = daziPage.getRecords().stream()
                                              .map(this::convertToListVo)
                                              .collect(Collectors.toList());
        voPage.setRecords(voList);
        
        log.info("获取我发布的搭子成功，总数: {}", voPage.getTotal());
        return voPage;
    }

    @Override
    public Page<YunkeDaziListVo> getMyJoinedDazi(Integer current, Integer size, Integer status) {
        // 检查登录状态
        YunkeSecurityUtil.checkLogin();
        Long userId = YunkeSecurityUtil.getCurrentUserId();
        
        log.info("获取我参与的搭子: userId={}, status={}", userId, status);
        
        // 先查询参与记录
        LambdaQueryWrapper<YunkeDaziJoin> joinWrapper = new LambdaQueryWrapper<>();
        joinWrapper.eq(YunkeDaziJoin::getUserId, userId)
                  .eq(YunkeDaziJoin::getIsPublisher, 0); // 排除发布者身份
        
        if (status != null) {
            joinWrapper.eq(YunkeDaziJoin::getStatus, status);
        } else {
            joinWrapper.in(YunkeDaziJoin::getStatus, 0, 1); // 待审核、已通过
        }
        
        joinWrapper.orderByDesc(YunkeDaziJoin::getCreateTime);
        
        List<YunkeDaziJoin> joinList = daziJoinMapper.selectList(joinWrapper);
        
        if (joinList.isEmpty()) {
            return new Page<>(current, size);
        }
        
        // 获取搭子ID列表
        List<Long> daziIds = joinList.stream()
                                   .map(YunkeDaziJoin::getDaziId)
                                   .collect(Collectors.toList());
        
        // 查询搭子信息
        LambdaQueryWrapper<YunkeDazi> daziWrapper = new LambdaQueryWrapper<>();
        daziWrapper.in(YunkeDazi::getId, daziIds);
        
        List<YunkeDazi> daziList = list(daziWrapper);
        
        // 手动分页
        int start = (current - 1) * size;
        int end = Math.min(start + size, daziList.size());
        List<YunkeDazi> pageData = daziList.subList(start, end);
        
        // 转换为VO
        Page<YunkeDaziListVo> voPage = new Page<>(current, size);
        voPage.setTotal(daziList.size());
        
        List<YunkeDaziListVo> voList = pageData.stream()
                                              .map(this::convertToListVo)
                                              .collect(Collectors.toList());
        voPage.setRecords(voList);
        
        log.info("获取我参与的搭子成功，总数: {}", voPage.getTotal());
        return voPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean editDazi(Long daziId, YunkeDaziCreateDto updateDto) {
        // 检查登录状态
        YunkeSecurityUtil.checkLogin();
        Long userId = YunkeSecurityUtil.getCurrentUserId();
        
        log.info("编辑搭子: userId={}, daziId={}", userId, daziId);
        
        // 验证搭子是否存在
        YunkeDazi dazi = getById(daziId);
        YunkeAssert.notNull(dazi, YunkeResultCode.DATA_NOT_FOUND, "搭子不存在");
        YunkeAssert.isTrue(dazi.getUserId().equals(userId), YunkeResultCode.FORBIDDEN, "只有发布者才能编辑搭子");
        YunkeAssert.isTrue(dazi.getStatus() != 2, YunkeResultCode.PARAM_ERROR, "已结束的搭子不能编辑");
        
        // 验证分类是否存在
        YunkeTabClass tabClass = tabClassMapper.selectById(updateDto.getTabClassId());
        YunkeAssert.notNull(tabClass, YunkeResultCode.PARAM_ERROR, "搭子分类不存在");
        YunkeAssert.isTrue(tabClass.getStatus() == 1, YunkeResultCode.PARAM_ERROR, "搭子分类已禁用");
        
        // 验证年龄范围
        if (updateDto.getAgeMin() != null && updateDto.getAgeMax() != null) {
            YunkeAssert.isTrue(updateDto.getAgeMin() <= updateDto.getAgeMax(), 
                              YunkeResultCode.PARAM_ERROR, "年龄范围设置错误");
        }
        
        // 验证活动时间
        long currentTime = System.currentTimeMillis();
        YunkeAssert.isTrue(updateDto.getActivityTime() > currentTime, 
                          YunkeResultCode.PARAM_ERROR, "活动时间不能早于当前时间");
        
        // 验证报名截止时间
        if (updateDto.getDeadlineTime() != null) {
            YunkeAssert.isTrue(updateDto.getDeadlineTime() < updateDto.getActivityTime(), 
                              YunkeResultCode.PARAM_ERROR, "报名截止时间不能晚于活动时间");
        }
        
        // 如果已有人参与，不能修改需要人数为更小的值
        if (dazi.getJoinedPeople() > 1 && updateDto.getNeedPeople() < dazi.getJoinedPeople()) {
            throw new YunkeException(YunkeResultCode.PARAM_ERROR, "需要人数不能少于已参与人数");
        }
        
        // 更新搭子信息
        BeanUtils.copyProperties(updateDto, dazi, "id", "userId", "joinedPeople", "status", 
                               "auditStatus", "isTop", "viewCount", "likeCount", "commentCount", 
                               "shareCount", "createTime", "publishTime");
        
        dazi.setUpdateTime(YunkeTimeUtil.timestampToLocalDateTime(System.currentTimeMillis()));
        
        // 处理图片列表
        if (updateDto.getImages() != null && !updateDto.getImages().isEmpty()) {
            try {
                dazi.setImages(objectMapper.writeValueAsString(updateDto.getImages()));
            } catch (JsonProcessingException e) {
                log.error("图片列表序列化失败: {}", e.getMessage());
                throw new YunkeException(YunkeResultCode.SYSTEM_ERROR, "图片数据处理失败");
            }
        } else {
            dazi.setImages(null);
        }
        
        // 保存更新
        boolean updateResult = updateById(dazi);
        YunkeAssert.isTrue(updateResult, YunkeResultCode.SYSTEM_ERROR, "编辑搭子失败");
        
        // 清除相关缓存
        redisTemplate.delete(CACHE_DAZI_DETAIL_KEY + daziId);
        redisTemplate.delete(CACHE_CATEGORY_KEY);
        
        log.info("编辑搭子成功: daziId={}, userId={}", daziId, userId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteDazi(Long daziId) {
        // 检查登录状态
        YunkeSecurityUtil.checkLogin();
        Long userId = YunkeSecurityUtil.getCurrentUserId();
        
        log.info("删除搭子: userId={}, daziId={}", userId, daziId);
        
        // 验证搭子是否存在
        YunkeDazi dazi = getById(daziId);
        YunkeAssert.notNull(dazi, YunkeResultCode.DATA_NOT_FOUND, "搭子不存在");
        YunkeAssert.isTrue(dazi.getUserId().equals(userId), YunkeResultCode.FORBIDDEN, "只有发布者才能删除搭子");
        
        // 检查是否有其他人参与
        LambdaQueryWrapper<YunkeDaziJoin> joinWrapper = new LambdaQueryWrapper<>();
        joinWrapper.eq(YunkeDaziJoin::getDaziId, daziId)
                  .eq(YunkeDaziJoin::getIsPublisher, 0)
                  .in(YunkeDaziJoin::getStatus, 0, 1); // 待审核或已通过
        
        long joinCount = daziJoinMapper.selectCount(joinWrapper);
        YunkeAssert.isTrue(joinCount == 0, YunkeResultCode.PARAM_ERROR, "已有用户参与的搭子不能删除，请先结束搭子");
        
        // 软删除搭子（更新状态为已删除）
        dazi.setStatus(4); // 已删除
        dazi.setUpdateTime(YunkeTimeUtil.timestampToLocalDateTime(System.currentTimeMillis()));
        
        boolean deleteResult = updateById(dazi);
        YunkeAssert.isTrue(deleteResult, YunkeResultCode.SYSTEM_ERROR, "删除搭子失败");
        
        // 删除发布者的参与记录
        LambdaQueryWrapper<YunkeDaziJoin> publisherWrapper = new LambdaQueryWrapper<>();
        publisherWrapper.eq(YunkeDaziJoin::getDaziId, daziId)
                       .eq(YunkeDaziJoin::getIsPublisher, 1);
        
        daziJoinMapper.delete(publisherWrapper);
        
        // 清除相关缓存
        redisTemplate.delete(CACHE_DAZI_DETAIL_KEY + daziId);
        redisTemplate.delete(CACHE_CATEGORY_KEY);
        redisTemplate.delete(CACHE_VIEW_COUNT_KEY + daziId);
        
        log.info("删除搭子成功: daziId={}, userId={}", daziId, userId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean topDazi(Long daziId, Integer topDays) {
        // 检查登录状态
        YunkeSecurityUtil.checkLogin();
        Long userId = YunkeSecurityUtil.getCurrentUserId();
        
        log.info("搭子置顶: userId={}, daziId={}, topDays={}", userId, daziId, topDays);
        
        // 验证搭子是否存在
        YunkeDazi dazi = getById(daziId);
        YunkeAssert.notNull(dazi, YunkeResultCode.DATA_NOT_FOUND, "搭子不存在");
        YunkeAssert.isTrue(dazi.getUserId().equals(userId), YunkeResultCode.FORBIDDEN, "只有发布者才能置顶搭子");
        YunkeAssert.isTrue(dazi.getStatus() == 1, YunkeResultCode.PARAM_ERROR, "只有已发布状态的搭子才能置顶");
        
        // 计算置顶结束时间
        long currentTime = System.currentTimeMillis();
        long topEndTime = currentTime + (topDays * 24 * 60 * 60 * 1000L);
        
        // 更新置顶信息
        LambdaUpdateWrapper<YunkeDazi> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(YunkeDazi::getId, daziId)
                   .set(YunkeDazi::getIsTop, 1)
                   .set(YunkeDazi::getTopTime, currentTime)
                   .set(YunkeDazi::getTopEndTime, topEndTime)
                   .set(YunkeDazi::getUpdateTime, currentTime);
        
        boolean updateResult = update(updateWrapper);
        YunkeAssert.isTrue(updateResult, YunkeResultCode.SYSTEM_ERROR, "搭子置顶失败");
        
        // 清除相关缓存
        redisTemplate.delete(CACHE_DAZI_DETAIL_KEY + daziId);
        redisTemplate.delete(CACHE_CATEGORY_KEY);
        
        log.info("搭子置顶成功: daziId={}, userId={}, topDays={}", daziId, userId, topDays);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean auditDazi(Long daziId, Integer auditStatus, String auditRemark) {
        // 检查登录状态
        YunkeSecurityUtil.checkLogin();
        Long auditorId = YunkeSecurityUtil.getCurrentUserId();
        
        log.info("搭子审核: auditorId={}, daziId={}, auditStatus={}", auditorId, daziId, auditStatus);
        
        // TODO: 验证审核员权限（可以根据用户角色或权限进行验证）
        // YunkeAssert.isTrue(hasAuditPermission(auditorId), YunkeResultCode.FORBIDDEN, "无审核权限");
        
        // 验证搭子是否存在
        YunkeDazi dazi = getById(daziId);
        YunkeAssert.notNull(dazi, YunkeResultCode.DATA_NOT_FOUND, "搭子不存在");
        YunkeAssert.isTrue(dazi.getAuditStatus() == 0, YunkeResultCode.PARAM_ERROR, "只能审核待审核状态的搭子");
        
        // 更新审核状态
        long currentTime = System.currentTimeMillis();
        LambdaUpdateWrapper<YunkeDazi> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(YunkeDazi::getId, daziId)
                   .set(YunkeDazi::getAuditStatus, auditStatus)
                   .set(YunkeDazi::getAuditRemark, auditRemark)
                   .set(YunkeDazi::getAuditorId, auditorId)
                   .set(YunkeDazi::getAuditTime, currentTime)
                   .set(YunkeDazi::getUpdateTime, currentTime);
        
        // 如果审核通过，设置发布时间
        if (auditStatus == 1) {
            updateWrapper.set(YunkeDazi::getPublishTime, currentTime);
        }
        
        boolean updateResult = update(updateWrapper);
        YunkeAssert.isTrue(updateResult, YunkeResultCode.SYSTEM_ERROR, "搭子审核失败");
        
        // 清除相关缓存
        redisTemplate.delete(CACHE_DAZI_DETAIL_KEY + daziId);
        redisTemplate.delete(CACHE_CATEGORY_KEY);
        
        String resultMsg = auditStatus == 1 ? "通过" : "拒绝";
        log.info("搭子审核成功: auditorId={}, daziId={}, result={}", auditorId, daziId, resultMsg);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean auditJoinApplication(Long joinId, Integer auditStatus, String auditRemark) {
        // 检查登录状态
        YunkeSecurityUtil.checkLogin();
        Long auditorId = YunkeSecurityUtil.getCurrentUserId();
        
        log.info("审核参与申请: auditorId={}, joinId={}, auditStatus={}", auditorId, joinId, auditStatus);
        
        // 查询参与记录
        YunkeDaziJoin joinRecord = daziJoinMapper.selectById(joinId);
        YunkeAssert.notNull(joinRecord, YunkeResultCode.DATA_NOT_FOUND, "参与记录不存在");
        YunkeAssert.isTrue(joinRecord.getStatus() == 0, YunkeResultCode.PARAM_ERROR, "只能审核待审核状态的申请");
        
        // 查询搭子信息
        YunkeDazi dazi = getById(joinRecord.getDaziId());
        YunkeAssert.notNull(dazi, YunkeResultCode.DATA_NOT_FOUND, "搭子不存在");
        YunkeAssert.isTrue(dazi.getUserId().equals(auditorId), YunkeResultCode.FORBIDDEN, "只有发布者才能审核参与申请");
        
        // 如果是通过审核，检查人数限制
        if (auditStatus == 1) {
            YunkeAssert.isTrue(dazi.getJoinedPeople() < dazi.getNeedPeople(), 
                              YunkeResultCode.PARAM_ERROR, "搭子人数已满，无法通过申请");
        }
        
        // 更新参与记录
        joinRecord.setStatus(auditStatus);
        joinRecord.setAuditRemark(auditRemark);
        joinRecord.setAuditorId(auditorId);
        joinRecord.setAuditTime(System.currentTimeMillis());
        joinRecord.setUpdateTime(YunkeTimeUtil.timestampToLocalDateTime(System.currentTimeMillis()));
        
        if (auditStatus == 1) { // 审核通过
            joinRecord.setJoinTime(System.currentTimeMillis());
            
            // 增加已加入人数
            LambdaUpdateWrapper<YunkeDazi> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(YunkeDazi::getId, joinRecord.getDaziId())
                       .setSql("joined_people = joined_people + 1");
            update(updateWrapper);
        }
        
        boolean updateResult = daziJoinMapper.updateById(joinRecord) > 0;
        YunkeAssert.isTrue(updateResult, YunkeResultCode.SYSTEM_ERROR, "审核申请失败");
        
        // 清除详情缓存
        redisTemplate.delete(CACHE_DAZI_DETAIL_KEY + joinRecord.getDaziId());
        
        String resultMsg = auditStatus == 1 ? "通过" : "拒绝";
        log.info("审核参与申请成功: auditorId={}, joinId={}, result={}", auditorId, joinId, resultMsg);
        return true;
    }

    @Override
    public void increaseViewCount(Long daziId) {
        // 使用Redis计数，定期同步到数据库
        String viewKey = CACHE_VIEW_COUNT_KEY + daziId;
        redisTemplate.opsForValue().increment(viewKey, 1);
        redisTemplate.expire(viewKey, 1, TimeUnit.DAYS);
        
        // 每10次浏览同步一次到数据库
        Object viewCount = redisTemplate.opsForValue().get(viewKey);
        if (viewCount != null && ((Integer) viewCount) % 10 == 0) {
            LambdaUpdateWrapper<YunkeDazi> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(YunkeDazi::getId, daziId)
                       .setSql("view_count = view_count + 10");
            update(updateWrapper);
        }
    }

    @Override
    public boolean likeDazi(Long daziId) {
        // 检查登录状态
        YunkeSecurityUtil.checkLogin();
        Long userId = YunkeSecurityUtil.getCurrentUserId();
        
        log.info("点赞搭子: userId={}, daziId={}", userId, daziId);
        
        // 验证搭子是否存在
        YunkeDazi dazi = getById(daziId);
        YunkeAssert.notNull(dazi, YunkeResultCode.DATA_NOT_FOUND, "搭子不存在");
        
        String likeKey = CACHE_LIKE_KEY + daziId + ":" + userId;
        
        // 检查是否已点赞
        Boolean isLiked = redisTemplate.hasKey(likeKey);
        
        if (Boolean.TRUE.equals(isLiked)) {
            // 取消点赞
            redisTemplate.delete(likeKey);
            
            // 减少点赞数
            LambdaUpdateWrapper<YunkeDazi> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(YunkeDazi::getId, daziId)
                       .setSql("like_count = like_count - 1");
            update(updateWrapper);
            
            log.info("取消点赞成功: userId={}, daziId={}", userId, daziId);
            return false; // 返回false表示取消点赞
        } else {
            // 点赞
            redisTemplate.opsForValue().set(likeKey, "1", 365, TimeUnit.DAYS);
            
            // 增加点赞数
            LambdaUpdateWrapper<YunkeDazi> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(YunkeDazi::getId, daziId)
                       .setSql("like_count = like_count + 1");
            update(updateWrapper);
            
            log.info("点赞成功: userId={}, daziId={}", userId, daziId);
            return true; // 返回true表示点赞成功
        }
    }

    @Override
    public boolean canJoinDazi(Long daziId, Long userId) {
        YunkeDazi dazi = getById(daziId);
        if (dazi == null || dazi.getStatus() != 1 || dazi.getAuditStatus() != 1) {
            return false;
        }
        
        // 检查是否是发布者
        if (dazi.getUserId().equals(userId)) {
            return false;
        }
        
        // 检查人数限制
        if (dazi.getJoinedPeople() >= dazi.getNeedPeople()) {
            return false;
        }
        
        // 检查报名截止时间
        if (dazi.getDeadlineTime() != null && System.currentTimeMillis() > dazi.getDeadlineTime()) {
            return false;
        }
        
        // 检查是否已经参与且状态不是已退出
        LambdaQueryWrapper<YunkeDaziJoin> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YunkeDaziJoin::getDaziId, daziId)
               .eq(YunkeDaziJoin::getUserId, userId)
               .in(YunkeDaziJoin::getStatus, 0, 1, 2); // 待审核、已通过、已拒绝
        
        return daziJoinMapper.selectCount(wrapper) == 0;
    }

    @Override
    public Page<YunkeDaziListVo> getNearbyDazi(String longitude, String latitude, Double radius, Integer current, Integer size) {
        log.info("获取附近搭子: longitude={}, latitude={}, radius={}km", longitude, latitude, radius);
        
        // TODO: 实现基于地理位置的距离计算查询
        // 这里先实现一个简化版本，后续可以集成Redis GEO或者ElasticSearch地理位置搜索
        
        // 构建查询条件
        LambdaQueryWrapper<YunkeDazi> wrapper = new LambdaQueryWrapper<>();
        
        // 基础过滤条件
        wrapper.eq(YunkeDazi::getStatus, 1) // 已发布
               .eq(YunkeDazi::getAuditStatus, 1); // 审核通过
        
        // 简化版本：如果有经纬度信息，按地点进行模糊匹配
        // 真实项目中应该使用地理位置索引进行精确距离计算
        if (StringUtils.hasText(longitude) && StringUtils.hasText(latitude)) {
            // 这里可以添加地理位置相关的查询逻辑
            // wrapper.apply("ST_Distance_Sphere(POINT(longitude, latitude), POINT({0}, {1})) <= {2}", 
            //              longitude, latitude, radius * 1000);
        }
        
        // 按距离排序（简化版本按发布时间排序）
        wrapper.orderByDesc(YunkeDazi::getIsTop)
               .orderByDesc(YunkeDazi::getPublishTime);
        
        // 分页查询
        Page<YunkeDazi> page = new Page<>(current, size);
        Page<YunkeDazi> daziPage = page(page, wrapper);
        
        // 转换为VO
        Page<YunkeDaziListVo> voPage = new Page<>();
        BeanUtils.copyProperties(daziPage, voPage, "records");
        
        List<YunkeDaziListVo> voList = daziPage.getRecords().stream().map(dazi -> {
            YunkeDaziListVo vo = convertToListVo(dazi);
            
            // 设置当前用户是否已参与
            if (YunkeSecurityUtil.isLogin()) {
                Long currentUserId = YunkeSecurityUtil.getCurrentUserId();
                boolean isJoined = checkUserJoined(dazi.getId(), currentUserId);
                vo.setIsJoined(isJoined ? 1 : 0);
            } else {
                vo.setIsJoined(0);
            }
            
            // TODO: 计算实际距离并设置到VO中
            // vo.setDistance(calculateDistance(longitude, latitude, dazi.getLongitude(), dazi.getLatitude()));
            
            return vo;
        }).collect(Collectors.toList());
        
        voPage.setRecords(voList);
        
        log.info("获取附近搭子成功，总数: {}", voPage.getTotal());
        return voPage;
    }

    @Override
    public Page<YunkeDaziListVo> getHotDazi(Integer current, Integer size) {
        log.info("获取热门搭子列表");
        
        // 构建查询条件
        LambdaQueryWrapper<YunkeDazi> wrapper = new LambdaQueryWrapper<>();
        
        // 基础过滤条件
        wrapper.eq(YunkeDazi::getStatus, 1) // 已发布
               .eq(YunkeDazi::getAuditStatus, 1); // 审核通过
        
        // 热门排序：置顶 > 点赞数 > 浏览量 > 评论数 > 发布时间
        wrapper.orderByDesc(YunkeDazi::getIsTop)
               .orderByDesc(YunkeDazi::getLikeCount)
               .orderByDesc(YunkeDazi::getViewCount)
               .orderByDesc(YunkeDazi::getCommentCount)
               .orderByDesc(YunkeDazi::getPublishTime);
        
        // 分页查询
        Page<YunkeDazi> page = new Page<>(current, size);
        Page<YunkeDazi> daziPage = page(page, wrapper);
        
        // 转换为VO
        Page<YunkeDaziListVo> voPage = new Page<>();
        BeanUtils.copyProperties(daziPage, voPage, "records");
        
        List<YunkeDaziListVo> voList = daziPage.getRecords().stream().map(dazi -> {
            YunkeDaziListVo vo = convertToListVo(dazi);
            
            // 设置当前用户是否已参与
            if (YunkeSecurityUtil.isLogin()) {
                Long currentUserId = YunkeSecurityUtil.getCurrentUserId();
                boolean isJoined = checkUserJoined(dazi.getId(), currentUserId);
                vo.setIsJoined(isJoined ? 1 : 0);
            } else {
                vo.setIsJoined(0);
            }
            
            return vo;
        }).collect(Collectors.toList());
        
        voPage.setRecords(voList);
        
        log.info("获取热门搭子成功，总数: {}", voPage.getTotal());
        return voPage;
    }

    @Override
    public Page<YunkeDaziListVo> searchDazi(String keyword, Integer current, Integer size) {
        log.info("搜索搭子: keyword={}", keyword);
        
        // 构建查询条件
        LambdaQueryWrapper<YunkeDazi> wrapper = new LambdaQueryWrapper<>();
        
        // 基础过滤条件
        wrapper.eq(YunkeDazi::getStatus, 1) // 已发布
               .eq(YunkeDazi::getAuditStatus, 1); // 审核通过
        
        // 关键词搜索：标题、内容、地点
        if (StringUtils.hasText(keyword)) {
            wrapper.and(w -> w.like(YunkeDazi::getTitle, keyword)
                           .or()
                           .like(YunkeDazi::getContent, keyword)
                           .or()
                           .like(YunkeDazi::getLocation, keyword));
        }
        
        // 按相关性和时间排序
        wrapper.orderByDesc(YunkeDazi::getIsTop)
               .orderByDesc(YunkeDazi::getViewCount)
               .orderByDesc(YunkeDazi::getPublishTime);
        
        // 分页查询
        Page<YunkeDazi> page = new Page<>(current, size);
        Page<YunkeDazi> daziPage = page(page, wrapper);
        
        // 转换为VO
        Page<YunkeDaziListVo> voPage = new Page<>();
        BeanUtils.copyProperties(daziPage, voPage, "records");
        
        List<YunkeDaziListVo> voList = daziPage.getRecords().stream().map(dazi -> {
            YunkeDaziListVo vo = convertToListVo(dazi);
            
            // 设置当前用户是否已参与
            if (YunkeSecurityUtil.isLogin()) {
                Long currentUserId = YunkeSecurityUtil.getCurrentUserId();
                boolean isJoined = checkUserJoined(dazi.getId(), currentUserId);
                vo.setIsJoined(isJoined ? 1 : 0);
            } else {
                vo.setIsJoined(0);
            }
            
            return vo;
        }).collect(Collectors.toList());
        
        voPage.setRecords(voList);
        
        log.info("搜索搭子成功，关键词: {}, 结果数: {}", keyword, voPage.getTotal());
        return voPage;
    }

    /**
     * 转换搭子实体为列表VO
     */
    private YunkeDaziListVo convertToListVo(YunkeDazi dazi) {
        YunkeDaziListVo vo = new YunkeDaziListVo();
        BeanUtils.copyProperties(dazi, vo);
        
        // 获取发布者信息
        YunkeUser publisher = userService.getById(dazi.getUserId());
        if (publisher != null) {
            vo.setPublisherNickname(publisher.getNickname());
            vo.setPublisherAvatar(publisher.getAvatar());
        }
        
        // 获取分类名称
        YunkeTabClass tabClass = tabClassMapper.selectById(dazi.getTabClassId());
        if (tabClass != null) {
            vo.setTabClassName(tabClass.getName());
        }
        
        // 处理封面图片
        if (StringUtils.hasText(dazi.getImages())) {
            try {
                List<String> images = objectMapper.readValue(dazi.getImages(), new TypeReference<List<String>>() {});
                if (!images.isEmpty()) {
                    vo.setCoverImage(images.get(0));
                }
            } catch (JsonProcessingException e) {
                log.warn("解析图片列表失败: daziId={}", dazi.getId());
            }
        }
        
        // 截取内容描述
        if (StringUtils.hasText(dazi.getContent()) && dazi.getContent().length() > 100) {
            vo.setContent(dazi.getContent().substring(0, 100) + "...");
        }
        
        // 计算是否可以参与
        if (YunkeSecurityUtil.isLogin()) {
            Long currentUserId = YunkeSecurityUtil.getCurrentUserId();
            vo.setCanJoin(canJoinDazi(dazi.getId(), currentUserId));
        } else {
            vo.setCanJoin(false);
        }
        
        // 计算热度评分
        double hotScore = calculateHotScore(dazi);
        vo.setHotScore(hotScore);
        
        return vo;
    }

    /**
     * 计算热度评分
     */
    private double calculateHotScore(YunkeDazi dazi) {
        // 综合考虑浏览量、点赞数、评论数、分享数和发布时间
        double viewWeight = 0.3;
        double likeWeight = 0.4;
        double commentWeight = 0.2;
        double shareWeight = 0.1;
        
        // 时间衰减因子
        long hours = (System.currentTimeMillis() - dazi.getPublishTime()) / (1000 * 60 * 60);
        double timeDecay = Math.max(0.1, 1.0 - (hours * 0.01)); // 每小时衰减1%
        
        double score = (dazi.getViewCount() * viewWeight +
                       dazi.getLikeCount() * likeWeight +
                       dazi.getCommentCount() * commentWeight +
                       dazi.getShareCount() * shareWeight) * timeDecay;
        
        return Math.round(score * 100.0) / 100.0; // 保留两位小数
    }

    /**
     * 检查用户是否已参与搭子
     */
    private boolean checkUserJoined(Long daziId, Long userId) {
        LambdaQueryWrapper<YunkeDaziJoin> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YunkeDaziJoin::getDaziId, daziId)
               .eq(YunkeDaziJoin::getUserId, userId)
               .in(YunkeDaziJoin::getStatus, 0, 1); // 待审核或已通过
        
        return daziJoinMapper.selectCount(wrapper) > 0;
    }

    /**
     * 转换搭子实体为详情VO
     */
    private YunkeDaziDetailVo convertToDetailVo(YunkeDazi dazi) {
        YunkeDaziDetailVo vo = new YunkeDaziDetailVo();
        BeanUtils.copyProperties(dazi, vo);
        
        // 获取发布者信息
        YunkeUser publisher = userService.getById(dazi.getUserId());
        if (publisher != null) {
            YunkeDaziDetailVo.PublisherInfo publisherInfo = new YunkeDaziDetailVo.PublisherInfo();
            publisherInfo.setUserId(publisher.getId());
            publisherInfo.setUsername(publisher.getUsername());
            publisherInfo.setNickname(publisher.getNickname());
            publisherInfo.setAvatar(publisher.getAvatar());
            publisherInfo.setGender(publisher.getGender());
            publisherInfo.setAge(publisher.getAge());
            publisherInfo.setVipLevel(publisher.getVipLevel());
            publisherInfo.setIsAuth(publisher.getIsAuth() != null && publisher.getIsAuth() ? 1 : 0);
            vo.setPublisherInfo(publisherInfo);
        }
        
        // 获取分类名称
        YunkeTabClass tabClass = tabClassMapper.selectById(dazi.getTabClassId());
        if (tabClass != null) {
            vo.setTabClassName(tabClass.getName());
        }
        
        // 处理图片列表
        if (StringUtils.hasText(dazi.getImages())) {
            try {
                List<String> images = objectMapper.readValue(dazi.getImages(), new TypeReference<List<String>>() {});
                vo.setImages(images);
            } catch (JsonProcessingException e) {
                log.warn("解析图片列表失败: daziId={}", dazi.getId());
                vo.setImages(new ArrayList<>());
            }
        } else {
            vo.setImages(new ArrayList<>());
        }
        
        // 获取参与成员列表
        List<YunkeDaziDetailVo.JoinMemberInfo> joinMembers = getJoinMembers(dazi.getId());
        vo.setJoinMembers(joinMembers);
        
        // 更新用户相关状态
        updateUserRelatedStatus(vo);
        
        return vo;
    }

    /**
     * 更新用户相关状态
     */
    private void updateUserRelatedStatus(YunkeDaziDetailVo vo) {
        if (YunkeSecurityUtil.isLogin()) {
            Long currentUserId = YunkeSecurityUtil.getCurrentUserId();
            
            // 检查是否已参与
            LambdaQueryWrapper<YunkeDaziJoin> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(YunkeDaziJoin::getDaziId, vo.getId())
                   .eq(YunkeDaziJoin::getUserId, currentUserId);
            
            YunkeDaziJoin joinRecord = daziJoinMapper.selectOne(wrapper);
            if (joinRecord != null) {
                vo.setIsJoined(1);
                vo.setJoinStatus(joinRecord.getStatus());
            } else {
                vo.setIsJoined(0);
                vo.setJoinStatus(null);
            }
            
            // 检查是否可以参与
            vo.setCanJoin(canJoinDazi(vo.getId(), currentUserId));
        } else {
            vo.setIsJoined(0);
            vo.setJoinStatus(null);
            vo.setCanJoin(false);
        }
    }

    /**
     * 获取参与成员列表
     */
    private List<YunkeDaziDetailVo.JoinMemberInfo> getJoinMembers(Long daziId) {
        LambdaQueryWrapper<YunkeDaziJoin> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YunkeDaziJoin::getDaziId, daziId)
               .eq(YunkeDaziJoin::getStatus, 1) // 已通过
               .orderByDesc(YunkeDaziJoin::getIsPublisher)
               .orderByAsc(YunkeDaziJoin::getJoinTime);
        
        List<YunkeDaziJoin> joinList = daziJoinMapper.selectList(wrapper);
        
        return joinList.stream().map(join -> {
            YunkeDaziDetailVo.JoinMemberInfo memberInfo = new YunkeDaziDetailVo.JoinMemberInfo();
            
            YunkeUser user = userService.getById(join.getUserId());
            if (user != null) {
                memberInfo.setUserId(user.getId());
                memberInfo.setUsername(user.getUsername());
                memberInfo.setNickname(user.getNickname());
                memberInfo.setAvatar(user.getAvatar());
                memberInfo.setGender(user.getGender());
                memberInfo.setAge(user.getAge());
            }
            
            memberInfo.setStatus(join.getStatus());
            memberInfo.setJoinTime(join.getJoinTime());
            memberInfo.setIsPublisher(join.getIsPublisher());
            
            return memberInfo;
        }).collect(Collectors.toList());
    }
} 